package com.rcn.db;

import com.rcn.dal.hibernate.ManagerDAO;
import com.rcn.dal.interfaces.IManagerDAO;
import com.rcn.hibernate.HibernateUtil;

import java.util.List;
import org.hibernate.*;

/**
 * NEVER log anything, DAO are responsible for that.
 * This class is responsible for the session, so ensure we close the session after perfor the query.
 * But in the methods we receive the session as a parameter we should leave it as it is.
 * @author Nicolas
 */
public class DBManager {
    private static DBManager manager;

    private DBManager(){
    }

    public static IManagerDAO getManagerDAO()
    {
    	return ManagerDAO.getInstance();
    }
    
    public static DBManager getDBManager(){
        if(manager==null){
        	manager=new DBManager();
        }
        return manager;
    }

    /**
     * Saves an entity
     * @param <T>
     * @param item
     * @throws HibernateException
     */
    public <T> long save(T item)throws HibernateException{
        Session session = HibernateUtil.getSession();
        long generatedId = -1;
        try
        {
            session.beginTransaction();
            generatedId = (Long) session.save(item);
            session.getTransaction().commit();
        }catch(HibernateException e){
            session.getTransaction().rollback();
            throw new HibernateException("Ocurrio un problema al guardar. "+e.getMessage());
        }finally{
        	if(HibernateUtil.getSession()!=null)
                HibernateUtil.getSession().close();
        }
        return generatedId;
    }

    /**
     * Gets an entity
     * @param clase
     * @param id
     * @return
     */
    public Object getData(Class clase,String id){
        Session session = HibernateUtil.getSession();
        //El metodo get devuelve null cuando ninguna fila corresponde con el id.
        Object loadedObject = null;
        try{
        	loadedObject = (Object)session.get(clase, Long.parseLong(id));
        }catch(HibernateException e){
        	throw e;
        }finally{
        	if(HibernateUtil.getSession()!=null)
                HibernateUtil.getSession().close();
        }
        return loadedObject;
    }
    
    /**
     * Gets all entity of a specific class
     * @return
     * @throws DataAccessLayerException
     */
     public List getAll(String tablename){
        List events = null;
        Session session = HibernateUtil.getSession();
        try{
        	Query query = session.createQuery("from "+tablename);
            events =  query.list();
        }catch(HibernateException e){
        	throw new HibernateException("Ocurrio un problema al actualizar. "+e.getMessage());
        }finally{
        	if(HibernateUtil.getSession()!=null)
                HibernateUtil.getSession().close();
        }
        return events;
    }

     /**
      * Updates an entity
      * @param <T>
      * @param item
      */
     public <T> void update(T item)throws HibernateException{
         Session session=HibernateUtil.getSession();
         try
         {
             session.beginTransaction();
             session.update(item);
             session.getTransaction().commit();
         }catch(HibernateException e){
            session.getTransaction().rollback();
            throw new HibernateException("Ocurrio un problema al actualizar. "+e.getMessage());
        }finally{
        	if(HibernateUtil.getSession()!=null)
                HibernateUtil.getSession().close();
        }
     }

     /**
      * saves or updates an entity
      * @param <T>
      * @param item
      * @throws HibernateException 
      */
     public <T> void saveOrUpdate(T item)throws HibernateException{
         Session session=HibernateUtil.getSession();
         try
         {
             session.beginTransaction();
             session.saveOrUpdate(item);
             session.getTransaction().commit();
         }catch(HibernateException e){
            session.getTransaction().rollback();
            throw new HibernateException("Ocurrio un problema al guardar o actualizar. "+e.getMessage());
        }finally{
        	if(HibernateUtil.getSession()!=null)
                HibernateUtil.getSession().close();
        }
     }
     
     /**
      * Saves or updates an entity an receives the entity as a parameter
      * @param item
      * @param s
      * @throws HibernateException
      */
     public <T> void saveOrUpdate(T item,Session s)throws HibernateException{
         try
         {
            s.saveOrUpdate(item);
         }catch(HibernateException e){
            throw new HibernateException("Ocurrio un problema al guardar o actualizar. "+e.getMessage());
        }
     }
     /**
      * Deletes an entity.
      * @param <T>
      * @param item
      */
     public <T> void delete(T item)throws HibernateException{
         Session session=HibernateUtil.getSession();
         try{
             session.beginTransaction();
             session.delete(item);
             session.getTransaction().commit();
         }catch(HibernateException e){
            session.getTransaction().rollback();
            throw new HibernateException("Ocurrio un problema al borrar. "+e.getMessage());
        }finally{
        	if(HibernateUtil.getSession()!=null)
                HibernateUtil.getSession().close();
        }
     }
     
     /**
      * Executes a query
      * @param <T>
      * @param item
      * @param q
      * @return 
      */
     public <T> List<T> executeQuery(String q){
         
         Session session=HibernateUtil.getSession();
         Query query = session.createQuery(q);
         List<T> results=null;
         try{
             session.beginTransaction();    
             results = query.list();
             session.getTransaction().commit();
         }catch(HibernateException e){
            session.getTransaction().rollback();
            throw new HibernateException("Ocurrio un problema al intentar ejecutar: "+q+". "+e.getMessage());
        }finally{
        	if(HibernateUtil.getSession() != null)
                HibernateUtil.getSession().close();
        }
         return results;
     }
}
